"""
聊天服务
实现知识库聊天相关的业务逻辑
"""

import logging
from datetime import datetime
from typing import Dict, Any, List
import aiohttp
import json
import urllib.parse

from sqlalchemy.ext.asyncio import AsyncSession

from config import settings
from schemas.base import KnowledgeBaseChatRequest, ChatMessage
from services.llm import LLMService
from services.knowledge import KnowledgeService

logger = logging.getLogger(__name__)


def _generate_simple_expanded_queries(query: str) -> List[str]:
    """
    生成简单的扩展查询，不调用LLM

    Args:
        query: 原始查询

    Returns:
        扩展查询列表
    """
    # 简单的查询扩展策略
    expanded_queries = [query]  # 保留原始查询

    # 添加一些常见的查询变体
    if "什么是" in query or "什么是" in query:
        # 提取关键词
        keywords = query.replace("什么是", "").replace("什么是", "").strip()
        if keywords:
            expanded_queries.extend([
                f"{keywords}",
                f"{keywords}是什么",
                f"{keywords}定义",
                f"{keywords}概念",
                f"{keywords}介绍"
            ])
    elif "如何" in query or "怎么" in query:
        # 提取关键词
        keywords = query.replace("如何", "").replace("怎么", "").strip()
        if keywords:
            expanded_queries.extend([
                f"{keywords}",
                f"{keywords}方法",
                f"{keywords}步骤",
                f"{keywords}教程"
            ])
    else:
        # 通用扩展
        expanded_queries.extend([
            f"{query}是什么",
            f"{query}定义",
            f"{query}概念",
            f"{query}介绍"
        ])

    # 去重并限制数量
    unique_queries = list(dict.fromkeys(expanded_queries))  # 保持顺序的去重
    return unique_queries[:5]  # 最多返回5个查询


class ChatService:
    """聊天服务类"""
    
    def __init__(self, db: AsyncSession):
        """
        初始化聊天服务
        
        Args:
            db: 数据库会话
        """
        self.db = db
        self.llm_service = None
        self.knowledge_service = KnowledgeService()


    async def yxy_chat(self, request: KnowledgeBaseChatRequest) -> Dict[str, Any]:
        """
        知识库聊天（基础版，不考虑知识库命中率）

        Args:
            request: 聊天请求参数

        Returns:
            聊天响应结果
        """
        async with LLMService() as llm_service:
            return await llm_service.knowledge_base_chat(
                query=request.query,
                knowledge_base_name=request.knowledge_base_name,
                temperature=request.temperature,
                max_tokens=request.max_tokens
            )


    async def knowledge_base_chat(self, request: KnowledgeBaseChatRequest) -> Dict[str, Any]:
        """
        知识库聊天（优化版，直接提高知识库命中率）
        
        Args:
            request: 聊天请求参数
            
        Returns:
            聊天响应结果
        """
        try:
            logger.info(f"开始知识库聊天，查询: {request.query}")
            
            # 1. 验证请求参数
            await self._validate_request(request)

            # 2. 初始化服务
            async with LLMService() as llm_service:
                # 4. 轻量级查询扩展 - 不调用LLM，直接生成简单扩展
                expanded_queries = _generate_simple_expanded_queries(request.query)
                logger.info(f"查询扩展完成，原始查询: {request.query}, 扩展查询: {expanded_queries}")
                
                # 5. 使用知识库服务搜索相关文档
                from services.knowledge import KnowledgeService
                knowledge_service = KnowledgeService()
                
                # 使用扩展查询搜索知识库
                search_results = []
                for expanded_query in expanded_queries[:settings.TOP_K]:
                    results = await knowledge_service.search_knowledge_base(
                        query=expanded_query,
                        knowledge_base_name=request.knowledge_base_name,
                        top_k=settings.TOP_K // 5,
                        score_threshold=settings.SCORE_THRESHOLD,
                        use_rerank=True
                    )
                    search_results.extend(results)
                
                # 去重和排序
                search_results = knowledge_service.deduplicate_results(search_results)
                search_results = search_results[:settings.TOP_K]  # 限制结果数量
                
                logger.info(f"知识库搜索完成，找到 {len(search_results)} 个相关文档")
                
                # 6. 处理知识库文档内容，获取整个知识库文档并结合用户问题生成增强答案
                documents_processing_result = await self._process_knowledge_base_documents(
                    request=request,
                    llm_service=llm_service
                )
                
                # 7. 整合文档处理结果和知识卡片搜索结果，调用LLM获取最终答案
                final_response = ""
                response_source = "llm"
                llm_response = {}
                
                try:
                    # 构建知识卡片上下文
                    knowledge_cards_context = self._build_context_from_search_results(search_results)
                    
                    # 获取文档处理结果
                    documents_answer = documents_processing_result.get("initial_answer", "")
                    documents_content = documents_processing_result.get("documents_content", "")

                    # 构建整合提示词，结合知识卡片和文档处理结果
                    integration_prompt = self._build_integration_prompt(
                        query=request.query,
                        knowledge_cards_context=knowledge_cards_context,
                        documents_answer=documents_answer,
                        documents_content=documents_content,
                        knowledge_base_name=request.knowledge_base_name,
                        prompt_name="default"  # 使用默认值，因为KnowledgeBaseChatRequest中没有prompt_name属性
                    )
                    
                    # 调用大模型，使用整合后的prompt
                    llm_response = await llm_service.chat_completion(
                        messages=[
                            {"role": "system", "content": f"你是{request.knowledge_base_name}知识库的专业智能助手，请根据提供的知识卡片和文档内容回答用户问题。"},
                            {"role": "user", "content": integration_prompt}
                        ],
                        stream=request.stream
                    )
                    final_response = llm_response.get("content", "")
                    response_source = "knowledge_base_integrated"
                    logger.info("成功使用知识库整合处理")
                    
                except Exception as e:
                    logger.warning(f"知识库整合处理失败，回退到基础LLM回答: {str(e)}")
                    # 回退到基础LLM回答
                    context = self._build_context_from_search_results(search_results)
                    llm_response = await llm_service.chat_completion(
                        messages=[
                            {"role": "system", "content": "你是一个专业知识库的助手，请根据提供的上下文回答用户问题。"},
                            {"role": "user", "content": f"基于以下上下文回答问题：\n\n上下文：{context}\n\n问题：{request.query}"}
                        ],
                        stream=True
                    )
                    final_response = llm_response.get("content", "")
                    response_source = "llm_fallback"

                
                # 8. 构建响应
                response_data = {
                    "status": "success",
                    "query": request.query,
                    "response": final_response,
                    "context": search_results,  # 使用知识库搜索结果作为上下文
                    "conversation_id": request.conversation_id,
                    "model": request.model_name,
                    "usage": llm_response.get("usage", {}) if response_source != "knowledge_base" else {},
                    "sources": search_results,  # 使用搜索结果作为来源
                    "expanded_queries": expanded_queries,
                    "search_results": search_results,  # 添加搜索结果
                    "response_source": response_source,  # 添加响应来源
                    "documents_processing": {
                        "processing_success": documents_processing_result.get("processing_success", False),
                        "file_count": documents_processing_result.get("file_count", 0),
                        "file_list": documents_processing_result.get("file_list", []),
                        "documents_content_length": len(documents_processing_result.get("documents_content", "")),
                        "initial_answer_length": len(documents_processing_result.get("initial_answer", "")),
                        "error": documents_processing_result.get("error", None)
                    },
                    "search_metadata": {
                        "total_results": len(search_results),
                        "avg_score": sum(r.get("score", 0) for r in search_results) / len(search_results) if search_results else 0,
                        "search_time": datetime.now().isoformat()
                    },
                    "timestamp": datetime.now().isoformat()
                }
                
                # 10. 保存对话记录（如果需要）
                if request.conversation_id:
                    await self._save_conversation(
                        conversation_id=request.conversation_id,
                        query=request.query,
                        response=final_response,
                        context=search_results,  # 使用知识库搜索结果
                        quality_assessment={
                            "type": "documents_processing",
                            "processing_success": documents_processing_result.get("processing_success", False),
                            "file_count": documents_processing_result.get("file_count", 0),
                            "response_source": response_source
                        }
                    )
                
                logger.info(f"知识库聊天完成，查询: {request.query}, 响应来源: {response_source}")
                return response_data
                
        except Exception as e:
            logger.error(f"知识库聊天失败: {str(e)}")
            raise
    
    def _evaluate_knowledge_quality(self, search_results: List[Dict[str, Any]], score_threshold: float) -> float:
        """
        评估知识库搜索结果质量
        
        Args:
            search_results: 搜索结果列表
            score_threshold: 相似度阈值
            
        Returns:
            质量分数 (0-10)
        """
        if not search_results:
            return 0.0
        
        # 计算质量分数
        total_score = 0.0
        factors = 0
        
        # 1. 结果数量因子 (0-3分)
        result_count = len(search_results)
        if result_count >= 5:
            count_score = 3.0
        elif result_count >= 3:
            count_score = 2.0
        elif result_count >= 1:
            count_score = 1.0
        else:
            count_score = 0.0
        total_score += count_score
        factors += 1
        
        # 2. 平均相似度因子 (0-4分)
        avg_similarity = sum(r.get("score", 0) for r in search_results) / len(search_results)
        similarity_score = min(4.0, avg_similarity * 4)  # 将0-1的相似度映射到0-4分
        total_score += similarity_score
        factors += 1
        
        # 3. 高相似度结果数量因子 (0-3分)
        high_quality_count = sum(1 for r in search_results if r.get("score", 0) >= score_threshold)
        if high_quality_count >= 3:
            quality_score = 3.0
        elif high_quality_count >= 1:
            quality_score = 2.0
        else:
            quality_score = 0.0
        total_score += quality_score
        factors += 1
        
        # 计算最终分数
        final_score = total_score / factors if factors > 0 else 0.0
        
        logger.info(f"知识库质量评估: 结果数量={result_count}({count_score}分), "
                   f"平均相似度={avg_similarity:.3f}({similarity_score:.1f}分), "
                   f"高质量结果={high_quality_count}({quality_score}分), "
                   f"最终分数={final_score:.1f}")
        
        return final_score

    def _build_context_from_search_results(self, search_results: List[Dict[str, Any]]) -> str:
        """
        从搜索结果构建上下文
        
        Args:
            search_results: 搜索结果列表
            
        Returns:
            构建的上下文字符串
        """
        if not search_results:
            return ""
        
        context_parts = []
        for i, result in enumerate(search_results, 1):
            content = result.get('content', '')
            score = result.get('score', 0)
            context_parts.append(f"文档{i} (相似度: {score:.3f}):\n{content}\n")
        
        return "\n".join(context_parts)

    def _build_enhanced_knowledge_prompt(
        self,
        query: str,
        context: str,
        knowledge_base_name: str,
        prompt_name: str = "default"
    ) -> str:
        """
        构建增强型知识库提示词
        
        Args:
            query: 用户查询
            context: 知识卡片上下文
            knowledge_base_name: 知识库名称
            prompt_name: 提示词模板名称
            
        Returns:
            增强型提示词
        """
        if prompt_name == "detailed":
            prompt_template = f"""你是{knowledge_base_name}知识库的专业智能助手。请仔细分析以下知识卡片内容，并结合用户问题给出详细、准确、专业的回答。

【知识卡片内容】
{context}

【用户问题】
{query}

【回答要求】
1. 基于知识卡片内容回答，不要编造信息
2. 如果知识卡片内容不足以回答问题，请明确说明
3. 回答要结构清晰，逻辑严谨
4. 如果涉及多个知识点，请分点说明
5. 使用专业术语，保持回答的权威性

请基于上述知识卡片内容，给出专业、准确、详细的回答："""
        
        elif prompt_name == "concise":
            prompt_template = f"""你是{knowledge_base_name}知识库的智能助手。请基于以下知识卡片内容，简洁明了地回答用户问题。

【知识卡片内容】
{context}

【用户问题】
{query}

请基于知识卡片内容，给出简洁、准确的回答："""
        
        else:  # default
            prompt_template = f"""你是{knowledge_base_name}知识库的智能助手。请结合下列知识卡片内容，回答用户的问题。

【知识卡片内容】
{context}

【用户问题】
{query}

请基于上述知识卡片内容，给出专业、准确、简明的回答。如果知识卡片内容不足以回答问题，请明确说明。"""
        
        logger.info(f"构建增强型提示词，知识库: {knowledge_base_name}, 模板: {prompt_name}")
        return prompt_template

    async def _enhanced_knowledge_search(
        self,
        query: str,
        knowledge_base_name: str,
        top_k: int,
        score_threshold: float
    ) -> List[Dict[str, Any]]:
        """
        增强的知识库搜索
        
        Args:
            query: 查询内容
            knowledge_base_name: 知识库名称
            top_k: 返回结果数量
            score_threshold: 相似度阈值
            
        Returns:
            搜索结果列表
        """
        try:
            # 使用知识库服务进行增强搜索
            search_results = await self.knowledge_service.search_knowledge_base(
                query=query,
                knowledge_base_name=knowledge_base_name,
                top_k=top_k,
                score_threshold=score_threshold,
                use_rerank=True
            )
            
            # 如果结果太少，降低阈值重新搜索
            if len(search_results) < top_k // 2:
                logger.info(f"搜索结果较少，降低阈值重新搜索")
                search_results = await self.knowledge_service.search_knowledge_base(
                    query=query,
                    knowledge_base_name=knowledge_base_name,
                    top_k=top_k,
                    score_threshold=score_threshold * 0.8,
                    use_rerank=True
                )
            
            return search_results
            
        except Exception as e:
            logger.error(f"增强知识库搜索失败: {str(e)}")
            # 降级到基础搜索
            return await self._search_knowledge_base(
                query=query,
                knowledge_base_name=knowledge_base_name,
                top_k=top_k,
                score_threshold=score_threshold
            )
    
    async def _build_enhanced_context(
        self, 
        search_results: List[Dict[str, Any]], 
        history: List[ChatMessage]
    ) -> str:
        """
        构建增强上下文
        
        Args:
            search_results: 搜索结果
            history: 历史对话
            
        Returns:
            构建的上下文字符串
        """
        context_parts = []
        
        # 添加知识库内容（按相关性排序）
        if search_results:
            context_parts.append("相关文档内容:")
            for i, result in enumerate(search_results, 1):
                content = result.get('content', '')
                score = result.get('score', 0)
                source = result.get('source', '')
                
                context_parts.append(f"{i}. [相关度: {score:.2f}] {content}")
                if source:
                    context_parts.append(f"   来源: {source}")
                
                # 添加元数据信息
                metadata = result.get('metadata', {})
                if metadata:
                    # 处理新的元数据格式
                    if 'head1' in metadata:
                        context_parts.append(f"   标题1: {metadata['head1']}")
                    if 'head2' in metadata:
                        context_parts.append(f"   标题2: {metadata['head2']}")
                    
                    # 处理原有的标签格式
                    tags = metadata.get('tags', [])
                    if tags:
                        context_parts.append(f"   标签: {', '.join(tags)}")
                    
                    # 添加其他有用的元数据
                    if 'id' in metadata:
                        context_parts.append(f"   文档ID: {metadata['id']}")
        
        # 添加历史对话（智能选择）
        if history:
            context_parts.append("\n历史对话:")
            # 只选择最近且相关的对话
            relevant_history = history[-3:]  # 最近3条
            for msg in relevant_history:
                role = "用户" if msg.role == "user" else "助手"
                context_parts.append(f"{role}: {msg.content}")
        
        # 添加上下文指导
        context_parts.append("\n指导原则:")
        context_parts.append("- 基于提供的文档内容回答用户问题")
        context_parts.append("- 如果文档内容不足以回答问题，请明确说明")
        context_parts.append("- 提供准确、有用的信息，避免猜测")
        context_parts.append("- 如果涉及多个方面，请分点说明")
        context_parts.append("- 优先使用文档中的具体信息，保持回答的准确性")
        
        return "\n".join(context_parts)
    
    async def _generate_enhanced_response(
        self,
        query: str,
        context: str,
        model_name: str,
        temperature: float,
        max_tokens: int,
        prompt_name: str
    ) -> str:
        """
        生成增强回复
        
        Args:
            query: 用户查询
            context: 上下文
            model_name: 模型名称
            temperature: 温度参数
            max_tokens: 最大token数
            prompt_name: 提示词模板名称
            
        Returns:
            生成的回复
        """
        try:
            # 构建增强提示词
            prompt = self._build_enhanced_prompt(query, context, prompt_name)
            
            messages = [
                {"role": "system", "content": "你是一个专业的AI助手，擅长基于知识库内容回答用户问题。"},
                {"role": "user", "content": prompt}
            ]
            
            # 调用LLM
            result = await self.llm_service.chat_completion(
                messages=messages,
                temperature=temperature,
                max_tokens=max_tokens if max_tokens > 0 else 1000,
                stream=True
            )
            
            return result["content"]
            
        except Exception as e:
            logger.error(f"生成增强回复失败: {str(e)}")
            # 降级到基础回复生成
            return await self._generate_response(
                query=query,
                context=context,
                model_name=model_name,
                temperature=temperature,
                max_tokens=max_tokens,
                prompt_name=prompt_name
            )
    
    def _build_enhanced_prompt(self, query: str, context: str, prompt_name: str) -> str:
        """
        构建增强提示词
        
        Args:
            query: 用户查询
            context: 上下文
            prompt_name: 提示词模板名称
            
        Returns:
            构建的提示词
        """
        if prompt_name == "default":
            return f"""请基于以下信息回答用户的问题。要求：
1. 准确理解用户问题
2. 基于提供的文档内容回答
3. 如果信息不足，请明确说明
4. 提供结构化的回答
5. 避免编造信息

相关信息：
{context}

用户问题：{query}

请提供准确、有用的回答："""
        else:
            # 可以添加其他提示词模板
            return f"用户问题：{query}\n\n相关信息：{context}\n\n请基于提供的信息回答问题："
    
    async def _assess_answer_quality(
        self,
        query: str,
        answer: str,
        context: List[Dict[str, Any]]
    ) -> Dict[str, Any]:
        """
        评估答案质量
        
        Args:
            query: 查询
            answer: 生成的答案
            context: 使用的上下文
            
        Returns:
            质量评估结果
        """
        try:
            if self.llm_service:
                return await self.llm_service.evaluate_answer_quality(query, answer, context)
            else:
                return {
                    "score": 5,
                    "reason": "LLM服务不可用",
                    "confidence": "低",
                    "context_count": len(context)
                }
        except Exception as e:
            logger.error(f"答案质量评估失败: {str(e)}")
            return {
                "score": 5,
                "reason": "评估失败",
                "confidence": "低",
                "context_count": len(context)
            }
    
    async def _validate_request(self, request: KnowledgeBaseChatRequest) -> None:
        """
        验证请求参数
        
        Args:
            request: 聊天请求参数
        """
        if not request.query or not request.query.strip():
            raise ValueError("查询内容不能为空")

    async def _search_knowledge_base(
        self, 
        query: str, 
        knowledge_base_name: str, 
        top_k: int, 
        score_threshold: float
    ) -> List[Dict[str, Any]]:
        """
        基础知识库搜索（降级方案）
        
        Args:
            query: 查询内容
            knowledge_base_name: 知识库名称
            top_k: 返回结果数量
            score_threshold: 相似度阈值
            
        Returns:
            搜索结果列表
        """
        # 基础搜索实现（保持原有逻辑作为降级方案）
        logger.info(f"使用基础搜索: {knowledge_base_name}, 查询: {query}")
        
        # 模拟搜索结果
        search_results = [
            {
                "content": f"这是关于'{query}'的相关内容1",
                "score": 0.95,
                "source": "document1.txt",
                "metadata": {"page": 1, "section": "introduction"}
            },
            {
                "content": f"这是关于'{query}'的相关内容2", 
                "score": 0.88,
                "source": "document2.txt",
                "metadata": {"page": 5, "section": "examples"}
            }
        ]
        
        # 过滤低于阈值的结果
        filtered_results = [
            result for result in search_results 
            if result["score"] >= score_threshold
        ]
        
        # 限制返回数量
        return filtered_results[:top_k]
    
    async def _build_context(
        self, 
        search_results: List[Dict[str, Any]], 
        history: List[ChatMessage]
    ) -> str:
        """
        构建基础上下文（降级方案）
        
        Args:
            search_results: 搜索结果
            history: 历史对话
            
        Returns:
            构建的上下文字符串
        """
        context_parts = []
        
        # 添加知识库内容
        if search_results:
            context_parts.append("相关文档内容:")
            for i, result in enumerate(search_results, 1):
                context_parts.append(f"{i}. {result['content']}")
                if result.get('source'):
                    context_parts.append(f"   来源: {result['source']}")
        
        # 添加历史对话
        if history:
            context_parts.append("\n历史对话:")
            for msg in history[-5:]:  # 只取最近5条
                role = "用户" if msg.role == "user" else "助手"
                context_parts.append(f"{role}: {msg.content}")
        
        return "\n".join(context_parts)
    
    async def _generate_response(
        self,
        query: str,
        context: str,
        model_name: str,
        temperature: float,
        max_tokens: int,
        prompt_name: str
    ) -> str:
        """
        生成基础回复（降级方案）
        
        Args:
            query: 用户查询
            context: 上下文
            model_name: 模型名称
            temperature: 温度参数
            max_tokens: 最大token数
            prompt_name: 提示词模板名称
            
        Returns:
            生成的回复
        """
        # 基础回复生成实现（保持原有逻辑作为降级方案）
        logger.info(f"使用基础回复生成，模型: {model_name}")
        
        # 构建提示词
        prompt = self._build_prompt(query, context, prompt_name)
        
        # 模拟LLM调用
        response = f"基于您的问题'{query}'，我为您提供以下回答：\n\n"
        response += "这是一个模拟的回复，实际实现时需要调用真实的LLM API。\n"
        response += f"使用的模型: {model_name}\n"
        response += f"温度参数: {temperature}\n"
        response += f"最大token数: {max_tokens if max_tokens > 0 else '无限制'}"
        
        return response
    
    def _build_prompt(self, query: str, context: str, prompt_name: str) -> str:
        """
        构建基础提示词（降级方案）
        
        Args:
            query: 用户查询
            context: 上下文
            prompt_name: 提示词模板名称
            
        Returns:
            构建的提示词
        """
        if prompt_name == "default":
            return f"""你是一个专业的助手，请基于以下信息回答用户的问题。

相关信息：
{context}

用户问题：{query}

请提供准确、有用的回答。如果相关信息不足以回答问题，请说明并建议用户提供更多信息。"""
        else:
            # 可以添加其他提示词模板
            return f"用户问题：{query}\n\n相关信息：{context}"
    
    async def _save_conversation(
        self,
        conversation_id: str,
        query: str,
        response: str,
        context: List[Dict[str, Any]],
        quality_assessment: Dict[str, Any] = None
    ) -> None:
        """
        保存对话记录
        
        Args:
            conversation_id: 对话ID
            query: 用户查询
            response: 助手回复
            context: 使用的上下文
            quality_assessment: 质量评估结果
        """
        # TODO: 实现对话记录保存逻辑
        # 这里可以保存到数据库或日志文件
        
        logger.info(f"保存对话记录，对话ID: {conversation_id}")
        
        # 模拟保存操作
        conversation_record = {
            "conversation_id": conversation_id,
            "query": query,
            "response": response,
            "context": context,
            "quality_assessment": quality_assessment,
            "timestamp": datetime.now().isoformat()
        }
        
        # 这里可以保存到数据库
        # await self._save_to_database(conversation_record)
        
        logger.info("对话记录保存完成")
    
    async def get_conversation_history(self, conversation_id: str) -> List[Dict[str, Any]]:
        """
        获取对话历史
        
        Args:
            conversation_id: 对话ID
            
        Returns:
            对话历史列表
        """
        # TODO: 实现从数据库获取对话历史
        logger.info(f"获取对话历史，对话ID: {conversation_id}")
        
        # 模拟返回历史记录
        return [
            {
                "role": "user",
                "content": "你好",
                "timestamp": "2024-01-01T10:00:00"
            },
            {
                "role": "assistant", 
                "content": "你好！我是您的AI助手，有什么可以帮助您的吗？",
                "timestamp": "2024-01-01T10:00:05"
            }
        ]

    async def _process_knowledge_base_documents(
        self,
        request: KnowledgeBaseChatRequest,
        llm_service: LLMService
    ) -> Dict[str, Any]:
        """
        处理知识库文档内容，获取整个知识库文档并结合用户问题生成增强答案
        
        Args:
            request: 聊天请求参数
            llm_service: LLM服务实例
            
        Returns:
            包含处理结果的字典
        """
        try:
            logger.info(f"开始处理知识库文档，知识库: {request.knowledge_base_name}")
            
            # 1. 获取知识库文件列表
            file_list = await self._get_knowledge_base_files(request.knowledge_base_name)
            if not file_list:
                logger.warning(f"知识库 {request.knowledge_base_name} 没有找到文件")
                return {
                    "documents_content": "",
                    "enhanced_answer": "",
                    "file_count": 0,
                    "processing_success": False
                }
            
            logger.info(f"获取到 {len(file_list)} 个文件")
            
            # 2. 下载所有文件内容
            all_documents_content = await self._download_all_documents(
                request.knowledge_base_name, 
                file_list
            )
            
            if not all_documents_content:
                logger.warning(f"知识库 {request.knowledge_base_name} 文件内容为空")
                return {
                    "documents_content": "",
                    "enhanced_answer": "",
                    "file_count": len(file_list),
                    "processing_success": False
                }
            
            logger.info(f"成功下载 {len(file_list)} 个文件，总内容长度: {len(all_documents_content)} 字符")
            
            # 3. 结合用户问题和整个文档内容调用LLM生成初步答案
            initial_answer = await self._split_and_process_documents(
                query=request.query,
                documents_content=all_documents_content,
                knowledge_base_name=request.knowledge_base_name,
                llm_service=llm_service,
                temperature=settings.TEMPERATURE,
                max_tokens=settings.MAX_TOKENS
            )
            
            logger.info(f"知识库文档处理完成，生成初步答案长度: {len(initial_answer)} 字符")
            
            return {
                "documents_content": all_documents_content,
                "initial_answer": initial_answer,
                "file_count": len(file_list),
                "file_list": file_list,
                "processing_success": True
            }
            
        except Exception as e:
            logger.error(f"处理知识库文档失败: {str(e)}")
            return {
                "documents_content": "",
                "enhanced_answer": "",
                "file_count": 0,
                "processing_success": False,
                "error": str(e)
            }
    
    async def _get_knowledge_base_files(self, knowledge_base_name: str) -> List[str]:
        """
        获取知识库文件列表
        
        Args:
            knowledge_base_name: 知识库名称
            
        Returns:
            文件名称列表
        """
        try:
            # URL编码知识库名称
            encoded_name = urllib.parse.quote(knowledge_base_name)
            url = f"http://172.16.21.142:7861/knowledge_base/list_files?knowledge_base_name={encoded_name}"
            
            async with aiohttp.ClientSession() as session:
                async with session.get(url, headers={'accept': 'application/json'}) as response:
                    if response.status == 200:
                        data = await response.json()
                        if data.get("code") == 200:
                            return data.get("data", [])
                        else:
                            logger.error(f"获取文件列表失败: {data.get('msg', '未知错误')}")
                            return []
                    else:
                        logger.error(f"获取文件列表HTTP错误: {response.status}")
                        return []
                        
        except Exception as e:
            logger.error(f"获取知识库文件列表异常: {str(e)}")
            return []
    
    async def _download_all_documents(self, knowledge_base_name: str, file_list: List[str]) -> str:
        """
        下载所有文档内容
        
        Args:
            knowledge_base_name: 知识库名称
            file_list: 文件名称列表
            
        Returns:
            合并后的文档内容
        """
        try:
            all_content = []
            encoded_name = urllib.parse.quote(knowledge_base_name)
            
            async with aiohttp.ClientSession() as session:
                for file_name in file_list:
                    try:
                        encoded_file_name = urllib.parse.quote(file_name)
                        url = f"http://172.16.21.142:7861/knowledge_base/download_doc?knowledge_base_name={encoded_name}&file_name={encoded_file_name}&preview=false"
                        
                        async with session.get(url, headers={'accept': 'application/json'}) as response:
                            if response.status == 200:
                                content = await response.text()
                                if content:
                                    all_content.append(f"【文件: {file_name}】\n{content}\n")
                                    logger.info(f"成功下载文件: {file_name}, 内容长度: {len(content)} 字符")
                                else:
                                    logger.warning(f"文件 {file_name} 内容为空")
                            else:
                                logger.warning(f"下载文件 {file_name} 失败，HTTP状态: {response.status}")
                    except Exception as e:
                        logger.error(f"下载文件 {file_name} 异常: {str(e)}")
                        continue
            
            return "\n".join(all_content)
            
        except Exception as e:
            logger.error(f"下载所有文档异常: {str(e)}")
            return ""
    
    async def _split_and_process_documents(
        self,
        query: str,
        documents_content: str,
        knowledge_base_name: str,
        llm_service: LLMService,
        temperature: float,
        max_tokens: int,
        chunk_size: int = settings.CHUNK_SIZE,
        overlap_size: int = 500
    ) -> str:
        """
        将长文档分割成小块，分别调用LLM生成答案，然后整合
        
        Args:
            query: 用户问题
            documents_content: 所有文档内容
            knowledge_base_name: 知识库名称
            llm_service: LLM服务实例
            temperature: 温度参数
            max_tokens: 最大token数
            chunk_size: 每个块的大小（字符数）
            overlap_size: 块之间的重叠大小（字符数）
            
        Returns:
            整合后的答案
        """
        try:
            logger.info(f"开始分割文档，总长度: {len(documents_content)} 字符")
            
            # 1. 分割文档
            document_chunks = self._split_document_into_chunks(
                documents_content, chunk_size, overlap_size
            )
            
            logger.info(f"文档分割完成，共 {len(document_chunks)} 个块")
            
            # 2. 为每个块生成提示词并调用LLM
            chunk_answers = []
            for i, chunk in enumerate(document_chunks):
                try:
                    logger.info(f"处理第 {i+1}/{len(document_chunks)} 个文档块，长度: {len(chunk)} 字符")
                    
                    # 构建提示词
                    prompt = f"""你是{knowledge_base_name}知识库的专业智能助手。请仔细分析以下文档片段，并结合用户问题给出准确、专业的回答。

【文档片段】
{chunk}

【用户问题】
{query}

【回答要求】
1. 基于提供的文档片段回答，不要编造信息
2. 如果文档片段内容不足以回答问题，请在回答结尾明确写上"未找到"
3. 回答要结构清晰，逻辑严谨
4. 如果涉及多个知识点，请分点说明
5. 使用专业术语，保持回答的权威性

请基于上述文档片段，给出专业、准确、详细的回答："""

                    logger.info(f"第 {i+1} 个块提示词长度: {len(prompt)} 字符")
                    
                    # 调用LLM
                    response = await llm_service.chat_completion(
                        messages=[
                            {"role": "system", "content": f"你是{knowledge_base_name}知识库的专业智能助手，请根据提供的文档片段回答用户问题。"},
                            {"role": "user", "content": prompt}
                        ],
                        stream=True
                    )
                    
                    answer = response.get("content", "").strip()
                    if answer:
                        chunk_answers.append({
                            "chunk_index": i,
                            "answer": answer,
                            "chunk_length": len(chunk)
                        })
                        logger.info(f"第 {i+1} 个块生成答案，长度: {len(answer)} 字符")
                    else:
                        logger.warning(f"第 {i+1} 个块生成答案为空")
                        
                except Exception as e:
                    logger.error(f"处理第 {i+1} 个文档块失败: {str(e)}")
                    continue
            
            # 3. 过滤掉结尾为"未找到"的答案
            valid_answers = []
            for chunk_answer in chunk_answers:
                answer = chunk_answer["answer"]
                if not answer.endswith("未找到") and not answer.endswith("未找到。") and not answer.endswith("未找到！"):
                    valid_answers.append(chunk_answer)
                else:
                    logger.info(f"过滤掉第 {chunk_answer['chunk_index']+1} 个块的答案（未找到相关信息）")
            
            logger.info(f"过滤后有效答案数量: {len(valid_answers)}")
            
            # 4. 如果没有有效答案，返回默认回答
            if not valid_answers:
                logger.warning("所有文档块都未找到相关信息")
                return "根据提供的文档内容，未找到与您问题相关的信息。"
            
            # 5. 整合所有有效答案
            integrated_answer = self._integrate_chunk_answers(valid_answers, query)
            
            logger.info(f"文档分割处理完成，最终答案长度: {len(integrated_answer)} 字符")
            return integrated_answer
            
        except Exception as e:
            logger.error(f"文档分割处理失败: {str(e)}")
            return ""

    def _split_document_into_chunks(
        self, 
        documents_content: str, 
        chunk_size: int, 
        overlap_size: int
    ) -> List[str]:
        """
        将文档内容分割成小块
        
        Args:
            documents_content: 文档内容
            chunk_size: 每个块的大小
            overlap_size: 块之间的重叠大小
            
        Returns:
            文档块列表
        """
        chunks = []
        start = 0
        
        while start < len(documents_content):
            end = start + chunk_size
            
            # 如果不是最后一块，尝试在句号、换行符等位置分割
            if end < len(documents_content):
                # 寻找合适的分割点
                split_chars = ['。', '\n\n', '\n', '；', '！', '？', '.', '!', '?']
                best_split = end
                
                for char in split_chars:
                    pos = documents_content.rfind(char, start, end)
                    if pos > start + chunk_size * 0.8:  # 在80%位置之后找到分割点
                        best_split = pos + 1
                        break
                
                end = best_split
            
            chunk = documents_content[start:end].strip()
            if chunk:
                chunks.append(chunk)
            
            # 计算下一个块的起始位置（考虑重叠）
            start = max(start + 1, end - overlap_size)
        
        return chunks

    def _integrate_chunk_answers(
        self, 
        chunk_answers: List[Dict[str, Any]], 
        query: str
    ) -> str:
        """
        整合多个文档块的答案
        
        Args:
            chunk_answers: 文档块答案列表
            query: 用户问题
            
        Returns:
            整合后的答案
        """
        try:
            if len(chunk_answers) == 1:
                return chunk_answers[0]["answer"]
            
            # 多个答案时，进行去重和整合
            logger.info(f"开始整合 {len(chunk_answers)} 个文档块的答案")
            
            # 提取所有答案内容
            answers = [chunk_answer["answer"] for chunk_answer in chunk_answers]
            
            # 简单的去重逻辑：移除完全重复的答案
            unique_answers = []
            for answer in answers:
                if answer not in unique_answers:
                    unique_answers.append(answer)
            
            logger.info(f"去重后答案数量: {len(unique_answers)}")
            
            # 如果只有一个唯一答案，直接返回
            if len(unique_answers) == 1:
                return unique_answers[0]
            
            # 多个答案时，进行整合
            integrated_parts = []
            integrated_parts.append(f"根据文档内容，为您提供以下相关信息：\n")
            
            for i, answer in enumerate(unique_answers, 1):
                # 清理答案格式
                cleaned_answer = answer.strip()
                if cleaned_answer:
                    # 移除可能的重复标题或开头
                    if cleaned_answer.startswith("根据文档内容"):
                        cleaned_answer = cleaned_answer[cleaned_answer.find("：")+1:].strip()
                    
                    integrated_parts.append(f"{i}. {cleaned_answer}\n")
            
            integrated_parts.append(f"\n以上信息综合了文档中的相关内容，希望能回答您的问题。")
            
            return "".join(integrated_parts)
            
        except Exception as e:
            logger.error(f"整合答案失败: {str(e)}")
            # 失败时返回第一个答案
            return chunk_answers[0]["answer"] if chunk_answers else ""

    async def _generate_initial_answer_from_documents(
        self,
        query: str,
        documents_content: str,
        knowledge_base_name: str,
        llm_service: LLMService,
        temperature: float,
        max_tokens: int
    ) -> str:
        """
        基于整个文档内容生成初步答案
        
        Args:
            query: 用户问题
            documents_content: 所有文档内容
            knowledge_base_name: 知识库名称
            llm_service: LLM服务实例
            temperature: 温度参数
            max_tokens: 最大token数
            
        Returns:
            初步答案
        """
        try:
            # 构建提示词，要求LLM基于整个文档内容回答问题
            prompt = f"""你是{knowledge_base_name}知识库的专业智能助手。请仔细分析以下完整的知识库文档内容，并结合用户问题给出准确、专业的回答。

【完整知识库文档内容】
{documents_content}

【用户问题】
{query}

【回答要求】
1. 基于完整的知识库文档内容回答，不要编造信息
2. 如果文档内容不足以回答问题，请明确说明
3. 回答要结构清晰，逻辑严谨
4. 如果涉及多个知识点，请分点说明
5. 使用专业术语，保持回答的权威性

请基于上述完整的知识库文档内容，给出专业、准确、详细的回答："""

            # 调用LLM生成初步答案（不传递knowledge_base_name，使用普通LLM接口）
            # 注意：普通LLM接口也返回流式响应，需要正确处理
            logger.info(f"开始调用LLM生成初步答案，文档内容长度: {len(documents_content)} 字符")
            logger.info(f"提示词长度: {len(prompt)} 字符")
            logger.info(f"温度参数: {temperature}, 最大token数: {max_tokens}")
            
            response = await llm_service.chat_completion(
                messages=[
                    {"role": "system", "content": f"你是{knowledge_base_name}知识库的专业智能助手，请根据提供的完整文档内容回答用户问题。"},
                    {"role": "user", "content": prompt}
                ],
                stream=True  # 改为True，使用流式响应
            )
            
            # 获取流式响应的完整内容
            initial_answer = response.get("content", "")
            logger.info(f"LLM响应对象: {response}")
            logger.info(f"基于完整文档生成初步答案，长度: {len(initial_answer)} 字符")
            
            # 如果内容为空，可能是流式响应处理有问题，记录详细信息
            if not initial_answer:
                logger.warning("初步答案为空，可能是流式响应处理问题")
                logger.warning(f"响应对象: {response}")
                logger.warning(f"响应类型: {type(response)}")
                logger.warning(f"响应键: {list(response.keys()) if isinstance(response, dict) else 'Not a dict'}")
            
            return initial_answer
            
        except Exception as e:
            logger.error(f"基于文档生成初步答案失败: {str(e)}")
            return ""
    
    async def _integrate_knowledge_cards_with_answer(
        self,
        initial_answer: str,
        search_results: List[Dict[str, Any]],
        query: str,
        knowledge_base_name: str,
        llm_service: LLMService,
        temperature: float,
        max_tokens: int
    ) -> str:
        """
        将初步答案与知识卡片信息整合，生成最终增强答案
        
        Args:
            initial_answer: 基于完整文档的初步答案
            search_results: 知识卡片搜索结果
            query: 用户问题
            knowledge_base_name: 知识库名称
            llm_service: LLM服务实例
            temperature: 温度参数
            max_tokens: 最大token数
            
        Returns:
            整合后的增强答案
        """
        try:
            # 构建知识卡片上下文
            knowledge_cards_context = self._build_context_from_search_results(search_results)
            
            # 构建整合提示词
            integration_prompt = f"""你是{knowledge_base_name}知识库的专业智能助手。现在需要你将基于完整文档生成的初步答案与高相关性的知识卡片信息进行整合，生成最终的增强答案。

【用户问题】
{query}

【基于完整文档的初步答案】
{initial_answer}

【高相关性知识卡片信息】
{knowledge_cards_context}

【整合要求】
1. 将初步答案与知识卡片信息进行智能整合
2. 去除重复信息，保持答案的简洁性
3. 补充知识卡片中的关键信息
4. 确保答案的准确性和完整性
5. 保持逻辑清晰，结构合理

请基于上述信息，生成最终的增强答案："""

            # 调用LLM进行整合（不传递knowledge_base_name，使用普通LLM接口）
            # 注意：普通LLM接口也返回流式响应，需要正确处理
            logger.info(f"开始调用LLM进行整合，初步答案长度: {len(initial_answer)} 字符")
            logger.info(f"知识卡片上下文长度: {len(knowledge_cards_context)} 字符")
            logger.info(f"整合提示词长度: {len(integration_prompt)} 字符")
            
            response = await llm_service.chat_completion(
                messages=[
                    {"role": "system", "content": f"你是{knowledge_base_name}知识库的专业智能助手，请将初步答案与知识卡片信息进行智能整合。"},
                    {"role": "user", "content": integration_prompt}
                ],
                stream=True
                # 不传递knowledge_base_name，避免调用知识库聊天接口
            )
            
            # 获取流式响应的完整内容
            enhanced_answer = response.get("content", "")
            logger.info(f"LLM整合响应对象: {response}")
            logger.info(f"整合知识卡片信息生成增强答案，长度: {len(enhanced_answer)} 字符")
            
            # 如果内容为空，可能是流式响应处理有问题，记录详细信息
            if not enhanced_answer:
                logger.warning("增强答案为空，可能是流式响应处理问题")
                logger.warning(f"响应对象: {response}")
                logger.warning(f"响应类型: {type(response)}")
                logger.warning(f"响应键: {list(response.keys()) if isinstance(response, dict) else 'Not a dict'}")
                # 如果整合失败，返回初步答案
                return initial_answer
            
            return enhanced_answer
            
        except Exception as e:
            logger.error(f"整合知识卡片信息失败: {str(e)}")
            # 如果整合失败，返回初步答案
            return initial_answer

    def _build_integration_prompt(
        self,
        query: str,
        knowledge_cards_context: str,
        documents_answer: str,
        documents_content: str,
        knowledge_base_name: str,
        prompt_name: str = "default"
    ) -> str:
        """
        构建整合提示词，结合知识卡片和文档处理结果
        
        Args:
            query: 用户查询
            knowledge_cards_context: 知识卡片上下文
            documents_answer: 基于文档的初步答案
            documents_content: 完整文档内容
            knowledge_base_name: 知识库名称
            prompt_name: 提示词模板名称
            
        Returns:
            整合提示词
        """
        if prompt_name == "detailed":
            prompt_template = f"""你是{knowledge_base_name}知识库的专业智能助手。现在需要你基于以下两个来源的信息，为用户问题提供最准确、最全面的回答：

【来源1：高相关性知识卡片】
{knowledge_cards_context}

【来源2：基于完整文档的初步分析】
{documents_answer}

【完整文档内容（供参考）】
{documents_content}

【用户问题】
{query}

【整合要求】
1. 将知识卡片的高相关性信息与文档的全面分析进行智能整合
2. 去除重复信息，保持答案的简洁性和逻辑性
3. 优先使用知识卡片中的高相关性信息
4. 补充文档分析中的关键细节和背景信息
5. 确保答案的准确性、完整性和权威性
6. 如果信息有冲突，以知识卡片信息为准
7. 保持专业术语的一致性

请基于上述两个来源的信息，给出专业、准确、全面、逻辑清晰的最终回答："""
        
        elif prompt_name == "concise":
            prompt_template = f"""你是{knowledge_base_name}知识库的智能助手。请基于以下信息，简洁明了地回答用户问题：

【知识卡片信息】
{knowledge_cards_context}

【文档分析结果】
{documents_answer}

【用户问题】
{query}

请整合上述信息，给出简洁、准确的回答："""
        
        else:  # default
            prompt_template = f"""你是{knowledge_base_name}知识库的智能助手。请基于以下两个信息源，为用户问题提供准确、专业的回答：

【高相关性知识卡片】
{knowledge_cards_context}

【基于完整文档的分析】
{documents_answer}

【用户问题】
{query}

【回答要求】
1. 智能整合两个信息源的内容
2. 去除重复，保持逻辑清晰
3. 确保信息的准确性和完整性
4. 如果知识卡片信息不足，补充文档分析中的相关内容
5. 保持专业性和权威性

请基于上述信息，给出专业、准确、完整的回答："""
        
        logger.info(f"构建整合提示词，知识库: {knowledge_base_name}, 模板: {prompt_name}")
        return prompt_template

